package com.fjwt.gz.sync.notify;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.aliyun.oss.ServiceException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fjwt.gz.core.constants.Constants;
import com.fjwt.gz.core.model.DBsecurityConfig;
import com.fjwt.gz.core.third.interfaces.IOfficialService;
import com.fjwt.gz.core.utils.SpringBeansUtil;
import com.fjwt.gz.db.entity.ActivityAppEntity;
import com.fjwt.gz.db.entity.ActivityChannelEntity;
import com.fjwt.gz.db.entity.ActivityEntity;
import com.fjwt.gz.db.entity.AgentAppEntity;
import com.fjwt.gz.db.entity.AgentEmployeeEntity;
import com.fjwt.gz.db.entity.AgentInfoEntity;
import com.fjwt.gz.db.entity.FansUserEntity;
import com.fjwt.gz.db.entity.MchInfoEntity;
import com.fjwt.gz.db.entity.OfficialMenuEntity;
import com.fjwt.gz.db.entity.OfficialReplyEntity;
import com.fjwt.gz.db.entity.SysConfig;
import com.fjwt.gz.service.impl.ActivityAppService;
import com.fjwt.gz.service.impl.ActivityChannelService;
import com.fjwt.gz.service.impl.ActivityService;
import com.fjwt.gz.service.impl.AgentAppService;
import com.fjwt.gz.service.impl.AgentEmployeeService;
import com.fjwt.gz.service.impl.AgentInfoService;
import com.fjwt.gz.service.impl.FansUserService;
import com.fjwt.gz.service.impl.MchInfoService;
import com.fjwt.gz.service.impl.OfficialMenuService;
import com.fjwt.gz.service.impl.OfficialReplyService;
import com.fjwt.gz.service.impl.SysConfigService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage;
import me.chanjar.weixin.cp.util.xml.XStreamTransformer;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.List;

@RestController
@Slf4j
public class WxNotifyController {

    @Autowired
    private ActivityService activityService;
    @Autowired
    private OfficialReplyService officialReplyService;
    @Autowired
    private OfficialMenuService officialMenusService;
    @Autowired
    private MchInfoService mchInfoService;
    @Autowired
    private AgentInfoService agentInfoService;
    @Autowired
    private AgentEmployeeService agentEmployeeService;
    @Autowired
    private FansUserService fansUserService;
    @Autowired
    private OfficialMenuService officialMenuService;
    @Autowired
    private ActivityAppService activityAppService;
    @Autowired
    private SysConfigService sysConfigService;
    @Autowired
    private ActivityChannelService activityChannelService;
    @Autowired
    private AgentAppService agentAppService;

    private static final String Token = "ckCI5CwzyXc90ugoQ8aO0ro42cNdMKKx";

    @PostMapping("/api/wx")
    public void syncPayOrder(HttpServletRequest request, HttpServletResponse response) throws Exception{
          // 事件消息推送的业务逻辑
        String body = getBody(request);
        log.info("请求头数据参数：{}",body);
        WxCpXmlMessage message = XStreamTransformer.fromXml(WxCpXmlMessage.class, body);
        log.info("解析正常参数信息：{}",JSON.toJSONString(message));
        SysConfig sysConfig = sysConfigService.getDbRedisByLikeConfigVal(SysConfig.class, message.getToUserName());
        DBsecurityConfig.WxOfficalBo wxOfficalBo = JSONObject.parseObject(sysConfig.getConfigVal(), DBsecurityConfig.WxOfficalBo.class);
        log.info("公众号配置参数：{}",JSON.toJSONString(sysConfig.getConfigVal()));
        // 扫描或关注公众号 事件推送，发送客服消息
        if("SCAN".equals(message.getEvent()) || "subscribe".equals(message.getEvent())){
            String eventKeyStr = "";
            if(message.getEventKey().contains("qrscene")){
                String[] s = message.getEventKey().split("_");
                eventKeyStr = s[1];
            }else{
                eventKeyStr = message.getEventKey();
            }
            if(StringUtils.isEmpty(eventKeyStr)){
                if("subscribe".equals(message.getEvent())){
                    log.info("关注公众号");
                    FansUserEntity userEntity = fansUserService.selectFansByOpenIdAndAppid("0", message.getFromUserName(), sysConfig.getConfigKey());
                    if (null != userEntity) {
                        userEntity.setIsFollow(0);
                        fansUserService.updateById(userEntity);
                    }
                }
                response.setCharacterEncoding("UTF-8");
                response.getWriter().println("success");
            } else {
                JSONObject eventKeyJson = JSONObject.parseObject(eventKeyStr);
                log.info("公众号生成二维码参数：{}", eventKeyStr);
                Long channelId = eventKeyJson.getLong("channelId");
                String channelCode = eventKeyJson.getString("channelCode");
                Integer channelType = eventKeyJson.getInteger("channelType");

                //获取不同渠道码类型的活动信息
                List<ActivityEntity> list = activityService.selectActivityListByChannelType(channelCode, channelType);
                if (ObjectUtils.isEmpty(list)) {
                    log.error("发送客服消息：未查询到渠道码活动");
//                    // 获取对应的渠道的公众号ID
                    ActivityChannelEntity activityChannel = activityChannelService.getById(channelId);
                    // 根据公众号的appid 获取对应的小程序
                    AgentAppEntity agentAppEntity = agentAppService.getAgentMinAppByOfficialAppId(activityChannel.getAppId());
                    // 公众号接口
                    IOfficialService service = SpringBeansUtil.getBean("officialWxChatService", IOfficialService.class);//todo 目前只有微信，后续再加其他的
                    // 发送客服消息的素材 封装参数
                    JSONObject json = new JSONObject();
                    json.put("mediaId", wxOfficalBo.getThumbMediaId());
                    json.put("openid", message.getFromUserName());
                    json.put("minAppid", agentAppEntity.getAppId());
                    json.put("title", sysConfig.getConfigName());
                    service.sendKefuMessage(json, activityChannel.getAppId(),officialMenuService.setWxService(activityChannel.getAppId()));
                }else {
                    ActivityEntity activityEntity = activityService.getById(list.get(0).getActivityId());
                    eventKeyJson.put("activityId", list.size() > 0 ? list.get(0).getActivityId() : "");
                    eventKeyJson.put("activityNum", list.size());
                    eventKeyJson.put("openId", message.getFromUserName());
                    eventKeyJson.put("date", DateUtil.format(DateUtil.date(), "yyyy-MM-dd"));
                    log.info("发送模板消息具体参数：{}", eventKeyJson.toJSONString());
                    String name = getChannelName(channelCode, channelType, list, activityEntity);

                    IOfficialService service = SpringBeansUtil.getBean("officialWxChatService", IOfficialService.class);

                    List<ActivityAppEntity> activityAppEntityList = activityAppService.list(
                            ActivityAppEntity.gw()
                                    .eq(ActivityAppEntity::getActivityId, activityEntity.getActivityId())
                    );
                    ActivityAppEntity activityAppEntitiesOfOfficial = activityAppEntityList.stream().filter(item -> item.getType().equals(Constants.AGENT_APP_TYPE.WX_OFFICIAL)).toList().get(0);
                    ActivityAppEntity activityAppEntitiesOfLite = activityAppEntityList.stream().filter(item -> item.getType().equals(Constants.AGENT_APP_TYPE.WX_LITE)).toList().get(0);

                    // 发送客服消息的素材 封装参数
                    JSONObject json = new JSONObject();
                    json.put("mediaId", activityEntity.getThumbMediaId());
                    json.put("openid", message.getFromUserName());
                    json.put("minAppid",activityAppEntitiesOfLite.getAppId());
                    json.put("eventKey", eventKeyJson.toJSONString());
                    json.put("title", name);
                    service.sendKefuMessage(json, activityAppEntitiesOfOfficial.getAppId(),officialMenuService.setWxService(activityAppEntitiesOfOfficial.getAppId()));
                }
            }
        }else if("CLICK".equals(message.getEvent())){
            clickEvent(response, message,sysConfig.getConfigKey());
        }else if ("VIEW".equals(message.getEvent())){
            log.info("跳转链接：{}",message.getEventKey());
            LambdaQueryWrapper<OfficialMenuEntity> menusQuery = new LambdaQueryWrapper<>();
            menusQuery.eq(OfficialMenuEntity::getOfficialAppId,sysConfig.getConfigKey());
            menusQuery.eq(OfficialMenuEntity::getType, "view");
            menusQuery.eq(OfficialMenuEntity::getUrl, message.getEventKey());
            menusQuery.eq(OfficialMenuEntity::getIsDeleted, 0);
            List<OfficialMenuEntity> list=  officialMenusService.getBaseMapper().selectList(menusQuery);
            if (ObjectUtils.isEmpty(list)){
                log.error("未找到对应的菜单信息，appid: {}, url: {}", sysConfig.getConfigKey(), message.getEventKey());
            }
            response.setCharacterEncoding("UTF-8");
            response.getWriter().println("success");
        }else if ("view_miniprogram".equals(message.getEvent())){
            log.info("跳转小程序：{}",message.getEventKey());
            LambdaQueryWrapper<OfficialMenuEntity> menusQuery = new LambdaQueryWrapper<>();
            menusQuery.eq(OfficialMenuEntity::getOfficialAppId,sysConfig.getConfigKey());
            menusQuery.eq(OfficialMenuEntity::getType, "miniprogram");
            menusQuery.eq(OfficialMenuEntity::getPagepath, message.getEventKey());
            menusQuery.eq(OfficialMenuEntity::getIsDeleted, 0);
            List<OfficialMenuEntity> list=  officialMenusService.getBaseMapper().selectList(menusQuery);
            if (ObjectUtils.isEmpty(list)){
                log.error("未找到对应的菜单信息，appid: {}, pagepath: {}", sysConfig.getConfigKey(), message.getEventKey());
            }
            response.setCharacterEncoding("UTF-8");
            response.getWriter().println("success");
        }else if("unsubscribe".equals(message.getEvent())){
            // 取消关注公众号事件推送
            log.info("用户取消关注公众号：用户openid{}",JSON.toJSONString(message.getFromUserName()));
            FansUserEntity userEntity = fansUserService.selectFansByOpenIdAndAppid("0", message.getFromUserName(), sysConfig.getConfigKey());
            if (userEntity != null) {
                userEntity.setIsFollow(1);
                fansUserService.updateById(userEntity);
            } else {
                log.error("未找到对应的 FansOpenidUserEntity 记录，openid: {}, appId: {}", message.getFromUserName(), sysConfig.getConfigKey());
            }
            response.setCharacterEncoding("UTF-8");
            response.getWriter().println("success");
        }else{
            LambdaQueryWrapper<OfficialReplyEntity> replyQueryWrapper = new LambdaQueryWrapper<>();
            replyQueryWrapper.eq(OfficialReplyEntity::getOfficialAppId,sysConfig.getConfigKey());
            replyQueryWrapper.eq(OfficialReplyEntity::getIsDeleted,0);
            replyQueryWrapper.like(OfficialReplyEntity::getReqKeyword,message.getContent());
            List<OfficialReplyEntity> list = officialReplyService.getBaseMapper().selectList(replyQueryWrapper);
            if(list.size()>0){
                for(OfficialReplyEntity entity:list){
                    log.info("被动回复消息参数：{}",JSONObject.toJSONString(entity));
                    // 全匹配
                    if(1==entity.getRepMate() && entity.getReqKeyword().equals(message.getContent())){
                        String msgStr = sendMessage(message,entity);
                        response.setCharacterEncoding("UTF-8");
                        response.getWriter().println(msgStr);
                    }
                    // 半匹配
                    if(2== entity.getRepMate() && entity.getReqKeyword().contains(message.getContent())){
                        String msgStr = sendMessage(message,entity);
                        response.setCharacterEncoding("UTF-8");
                        response.getWriter().println(msgStr);
                    }
                }
            }
            response.setCharacterEncoding("UTF-8");
            response.getWriter().println("success");
        }
    }

    private void clickEvent(HttpServletResponse response, WxCpXmlMessage message, String appid) throws IOException {
        LambdaQueryWrapper<OfficialMenuEntity> menusQuery = new LambdaQueryWrapper<>();
        menusQuery.eq(OfficialMenuEntity::getOfficialAppId, appid);
        menusQuery.eq(OfficialMenuEntity::getType, "click");
        List<OfficialMenuEntity> list=  officialMenusService.getBaseMapper().selectList(menusQuery);
        log.info("公众号点击菜单事件：{}",JSONObject.toJSONString(list));
        for(OfficialMenuEntity dto:list){
            if(dto.getMenuKey().equals(message.getEventKey())){
                OfficialReplyEntity entity = new OfficialReplyEntity();
                BeanUtil.copyProperties(dto,entity);
                String msgStr = sendMessage(message,entity);
//                    String msgStr = "<xml>\n" +
//                            "  <ToUserName><![CDATA["+message.getFromUserName()+"]]></ToUserName>\n" +
//                            "  <FromUserName><![CDATA["+message.getToUserName()+"]]></FromUserName>\n" +
//                            "  <CreateTime>"+ DateUtil.current() +"</CreateTime>\n" +
//                            "  <MsgType><![CDATA[image]]></MsgType>\n" +
//                            "  <Image>\n" +
//                            "    <MediaId><![CDATA[Kx1NOB16X9VDQhX5r-2h9tbDB17xF0wk2-a0jV9tZ_6BEqjCxHyJtcUHNvz2ms5K]]></MediaId>\n" +
//                            "  </Image>\n" +
//                            "</xml>";
                response.setCharacterEncoding("UTF-8");
                response.getWriter().println(msgStr);
            }
        }
    }

    private String sendMessage(WxCpXmlMessage message,OfficialReplyEntity entity){
        if("text".equals(entity.getRepType())){
           return sendTextMessage(message,entity);
        }
        if("image".equals(entity.getRepType())){
            return sendImageMessage(message,entity);
        }
        if("news".equals(entity.getRepType())){
            return sendNewsMessage(message,entity);
        }
        if("voice".equals(entity.getRepType())){
           return sendVoiceMessage(message,entity);
        }
        if("video".equals(entity.getRepType())){
            return sendVideoMessage(message,entity);
        }
        if("music".equals(entity.getRepType())){
            return sendMusicMessage(message,entity);
        }
        return "success";
    }

    /**获取不同类型的名称**/
    public String getChannelName(String channelCode,Integer channelType,List<ActivityEntity> list,ActivityEntity activityEntity){
        String name = "";
        if (0 == channelType){
            channelCode = channelCode.split("-")[1];
            LambdaQueryWrapper<AgentEmployeeEntity> gw = AgentEmployeeEntity.gw();
            gw.eq(AgentEmployeeEntity::getEmployeeNo,channelCode);
            AgentEmployeeEntity agentEmployeeEntity = agentEmployeeService.getOne(gw);
            name = agentEmployeeEntity.getEmployeeName();
            log.info("机构人员姓名：{}",name);
        }else if (1 == channelType){
            channelCode = channelCode.split("-")[1];
            MchInfoEntity mchInfo = mchInfoService.getById(channelCode);
            name = StringUtils.isNotEmpty(mchInfo.getMchShortName()) ? mchInfo.getMchShortName() : mchInfo.getMchName();
            log.info("商户名称：{}",name);
        }else if (2 == channelType){
            AgentInfoEntity agentInfo = agentInfoService.getById(channelCode);
            name = agentInfo.getAgentName();
            log.info("机构名称：{}",name);
        }
        if (list.size() > 1) {
            name = "点击查看【" + name + "】优惠活动";
        } else {
            name = activityEntity.getActivityName();
        }
        return name;
    }

    // 文本消息
    public String sendTextMessage(WxCpXmlMessage message,OfficialReplyEntity entity){
        String str = "<xml>\n" +
                "  <ToUserName><![CDATA["+message.getFromUserName()+"]]></ToUserName>\n" +
                "  <FromUserName><![CDATA["+message.getToUserName()+"]]></FromUserName>\n" +
                "  <CreateTime>"+ DateUtil.current() +"</CreateTime>\n" +
                "  <MsgType><![CDATA[text]]></MsgType>\n" +
                "  <Content><![CDATA["+entity.getRepContent()+"]]></Content>\n" +
                "</xml>";
        return str;
    }

    // 图片消息
    public String sendImageMessage(WxCpXmlMessage message,OfficialReplyEntity entity){
        String str = "<xml>\n" +
                "  <ToUserName><![CDATA["+message.getFromUserName()+"]]></ToUserName>\n" +
                "  <FromUserName><![CDATA["+message.getToUserName()+"]]></FromUserName>\n" +
                "  <CreateTime>"+ DateUtil.current() +"</CreateTime>\n" +
                "  <MsgType><![CDATA[image]]></MsgType>\n" +
                "  <Image>\n" +
                "    <MediaId><![CDATA["+entity.getRepMediaId()+"]]></MediaId>\n" +
                "  </Image>\n" +
                "</xml>";
        return str;
    }
    // 图文消息
    public String sendNewsMessage(WxCpXmlMessage message,OfficialReplyEntity entity){
        String str = "<xml>\n" +
                "  <ToUserName><![CDATA["+message.getFromUserName()+"]]></ToUserName>\n" +
                "  <FromUserName><![CDATA["+message.getToUserName()+"]]></FromUserName>\n" +
                "  <CreateTime>"+ DateUtil.current() +"</CreateTime>\n" +
                "  <MsgType><![CDATA[news]]></MsgType>\n" +
                "  <ArticleCount>1</ArticleCount>\n" +
                "  <Articles>\n" +
                "    <item>\n" +
                "      <Title><![CDATA["+entity.getRepName()+"]]></Title>\n" +
                "      <Description><![CDATA["+entity.getRepDesc()+"]]></Description>\n" +
                "      <PicUrl><![CDATA["+entity.getRepUrl()+"]]></PicUrl>\n" +
                "      <Url><![CDATA["+entity.getRepUrl()+"]]></Url>\n" +
                "    </item>\n" +
                "  </Articles>\n" +
                "</xml>";
        return str;
    }
    // 语音消息
    public String sendVoiceMessage(WxCpXmlMessage message,OfficialReplyEntity entity){
        String str = "<xml>\n" +
                "  <ToUserName><![CDATA["+message.getFromUserName()+"]]></ToUserName>\n" +
                "  <FromUserName><![CDATA["+message.getToUserName()+"]]></FromUserName>\n" +
                "  <CreateTime>"+ DateUtil.current() +"</CreateTime>\n" +
                "  <MsgType><![CDATA[voice]]></MsgType>\n" +
                "  <Voice>\n" +
                "    <MediaId><![CDATA["+entity.getRepMediaId()+"]]></MediaId>\n" +
                "  </Voice>\n" +
                "</xml>";
        return str;
    }
    // 视频消息
    public String sendVideoMessage(WxCpXmlMessage message,OfficialReplyEntity entity){
        String str = "<xml>\n" +
                "  <ToUserName><![CDATA["+message.getFromUserName()+"]]></ToUserName>\n" +
                "  <FromUserName><![CDATA["+message.getToUserName()+"]]></FromUserName>\n" +
                "  <CreateTime>"+ DateUtil.current() +"</CreateTime>\n" +
                "  <MsgType><![CDATA[video]]></MsgType>\n" +
                "  <Video>\n" +
                "    <MediaId><![CDATA["+entity.getRepMediaId()+"]]></MediaId>\n" +
                "    <Title><![CDATA["+entity.getRepName()+"]]></Title>\n" +
                "    <Description><![CDATA["+entity.getRepDesc()+"]]></Description>\n" +
                "  </Video>\n" +
                "</xml>\n";
        return str;
    }
    // 音乐消息
    public String sendMusicMessage(WxCpXmlMessage message,OfficialReplyEntity entity){
        String str = "<xml>\n" +
                "  <ToUserName><![CDATA["+message.getFromUserName()+"]]></ToUserName>\n" +
                "  <FromUserName><![CDATA["+message.getToUserName()+"]]></FromUserName>\n" +
                "  <CreateTime>"+ DateUtil.current() +"</CreateTime>\n" +
                "  <MsgType><![CDATA[music]]></MsgType>\n" +
                "  <Music>\n" +
                "    <Title><![CDATA["+entity.getRepName()+"]]></Title>\n" +
                "    <Description><![CDATA["+entity.getRepDesc()+"]]></Description>\n" +
                "    <MusicUrl><![CDATA["+entity.getRepUrl()+"]]></MusicUrl>\n" +
                "    <HQMusicUrl><![CDATA["+entity.getRepHqUrl()+"]]></HQMusicUrl>\n" +
                "    <ThumbMediaId><![CDATA["+entity.getRepThumbMediaId()+"]]></ThumbMediaId>\n" +
                "  </Music>\n" +
                "</xml>";
        return str;
    }

    protected final String getBody(HttpServletRequest request) {
        InputStreamReader in = null;
        try {
            in = new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8);
            StringBuffer bf = new StringBuffer();
            int len;
            char[] chs = new char[1024];
            while ((len = in.read(chs)) != -1) {
                bf.append(new String(chs, 0, len));
            }
            return bf.toString();
        } catch (Exception e) {
            log.error("请求头部取数据异常：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        } finally {
            if (null != in) {
                try {
                    in.close();
                } catch (Exception e) {
                    log.error("流关闭异常:{}", e.getMessage());
                }
            }
        }
    }
}
